<template>
  <div>
    <slot>
      <el-select
        ref="selectRef"
        v-model="selectedIds"
        filterable
        remote
        collapse-tags
        clearable
        :style="`width: ${width}px`"
        placeholder="请选择"
        :multiple="multiple"
        :disabled="disabled"
        @focus="onOpen"
        @remove-tag="onRemoveTag"
        @clear="onClearTag"
      >
        <el-option
          v-for="item in selectedOptions"
          :key="item.value"
          :value="item.value"
          :label="item.label"
          style="display: none"
        />
      </el-select>
    </slot>
    <el-dialog
      v-model="dialogVisible"
      title="请选择"
      width="80%"
      :append-to-body="true"
      :destroy-on-close="true"
      @close="onClose"
    >
      <component
        ref="currentComponentRef"
        :is="dialogComponents.get(componentName)"
        :mode="multiple ? 'dialog-multiple' : 'dialog-single'"
        :selectedRows="selectedList"
        @selection-change="selectChange"
      ></component>
      <template #footer v-if="multiple">
        <span class="dialog-footer">
          <el-button @click="onClose">取 消</el-button>
          <el-button type="primary" @click="onConfirm">确 定</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script lang="ts">
export default {
  name: "TableSelect",
};
</script>
<script lang="ts" setup>
const defaultOptionsAlias = {
  label: "name",
  value: "id",
}

const props = defineProps({
  width: {
    type: [String, Number],
    default: 250,
  },
  // 下拉选项别名
  optionAlias: {
    type: Object,
    default: () => ({
      label: "name",
      value: "id",
    }),
  },
  multiple: {
    type: Boolean,
    default: true,
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  selectedList: {
    type: [Array, Object],
    default: () => ([]),
  },
  // 动态组件名称
  componentName: {
    type: String,
    default: "",
  },
});

const emit = defineEmits(["update:selectedList"]);

const selectRef = ref();

const selectChange = (newValue: any[]) => {
  emit("update:selectedList", newValue)
};

const selectedOptions = computed(() => {
  const optionAlias = {
    ...defaultOptionsAlias,
    ...props.optionAlias
  }
  return props.selectedList.map((item: any) => {
    return {
      label: item[optionAlias.label],
      value: item[optionAlias.value],
    }
  })
})
const selectedIds = ref<any[]>([])
watch(selectedOptions, () => {
  const { multiple } = props
  if (multiple) {
    selectedIds.value = selectedOptions.value.map((v: any) => v.value);
  } else {
    selectedIds.value =  !selectedOptions.value.length ? [] : selectedOptions.value[0]
  }
})

// 移除一项
const onRemoveTag = (val: any) => {
  const valueAlias = props.optionAlias.value || defaultOptionsAlias.value
  const newList = props.selectedList?.filter((v: any) => v[valueAlias] !== val);
  selectChange(newList)
};
// 清空
const onClearTag = () => {
  selectChange([])
};

// 弹窗start
// 表格实例
const currentComponentRef = ref();

const dialogComponents = ref(new Map<string, any>());
dialogComponents.value.set(
  "TableA",
  markRaw(
    defineAsyncComponent(
      () => import("@/views/table/components/TableA.vue")
    )
  )
);

const dialogVisible = ref(false);
// 打开弹窗
const onOpen = () => {
  dialogVisible.value = true;
};
// 关闭弹窗
const onClose = () => {
  dialogVisible.value = false;
};
const onConfirm = () => {
  dialogVisible.value = false;
};
// 弹窗end

// 暴露变量
defineExpose({
  onOpen
});
</script>

<style lang="scss" scoped></style>
